package com.pig4cloud.pig.ads.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.pig4cloud.pig.ads.pig.mapper.AdPlanTempMapper;
import com.pig4cloud.pig.ads.pig.mapper.AudiencePackageMapper;
import com.pig4cloud.pig.ads.service.AdPlanTempService;
import com.pig4cloud.pig.ads.service.AudiencePackageService;
import com.pig4cloud.pig.ads.service.TtAccesstokenService;
import com.pig4cloud.pig.ads.utils.DateUtils;
import com.pig4cloud.pig.api.dto.AdActionInterestDTO;
import com.pig4cloud.pig.api.dto.AdPlanTempDto;
import com.pig4cloud.pig.api.entity.AdPlanTemp;
import com.pig4cloud.pig.api.entity.AudiencePackage;
import com.pig4cloud.pig.api.enums.TtConvertTypeEnum;
import com.pig4cloud.pig.api.enums.TtDeepExternalActionEnum;
import com.pig4cloud.pig.api.vo.AdPlanTempVo;
import com.pig4cloud.pig.common.core.exception.BusinessException;
import com.pig4cloud.pig.common.core.util.DateUtil;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 广告计划临时 服务层实现
 *
 * @author hma
 * @date 2020-11-18
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class AdPlanTempServiceImpl extends ServiceImpl<AdPlanTempMapper, AdPlanTemp> implements AdPlanTempService {

	private static final String ACTION_CATEGORY_URI = "https://ad.oceanengine.com/open_api/2/tools/interest_action/action/category/";
	private static final String ACTION_KEYWORD_URI = "https://ad.oceanengine.com/open_api/2/tools/interest_action/action/keyword/";
	private static final String INTEREST_CATEGORY_URI = "https://ad.oceanengine.com/open_api/2/tools/interest_action/interest/category/";
	private static final String INTEREST_KEYWORD_URI = "https://ad.oceanengine.com/open_api/2/tools/interest_action/interest/keyword/";
	private static final String ACTION_INTEREST_KEYWORD_URI = "https://ad.oceanengine.com/open_api/2/tools/interest_action/keyword/suggest/";
	private static final Collection<String> DEFAULT_ACTION_SCENES = Arrays.asList("E-COMMERCE", "NEWS", "APP", "SEARCH");

	private final TtAccesstokenService ttAccesstokenService;

	private final AudiencePackageService audiencePackageService;

	private final AudiencePackageMapper audiencePackageMapper;

	/**
	 * 行为类目列表查询
	 *
	 * @param planTemp
	 * @return
	 */
	@Override
	public List<AdActionInterestDTO> selectActionCategoryList(AdPlanTempDto planTemp) throws IOException {
		// 参数校验
		Optional<AdPlanTempDto> planTempOps = Optional.ofNullable(planTemp);
		Long advertiserId = planTempOps.map(AdPlanTempDto::getAdvertiserId).orElseThrow(NullPointerException::new);

		// 构造请求参数
		JSONObject requestBody = new JSONObject().fluentPut("advertiser_id", advertiserId)
				.fluentPut("action_scene", planTempOps.map(AdPlanTempDto::getActionScenes).filter(CollectionUtil::isNotEmpty).orElse(DEFAULT_ACTION_SCENES))
				.fluentPut("action_days", planTempOps.map(AdPlanTempDto::getActionDays1).orElseThrow(NullPointerException::new));

		// 获取token
		String accessToken = Objects.requireNonNull(ttAccesstokenService.fetchAccesstoken(String.valueOf(advertiserId)), "没有找到有效的AccessToken");

		// 请求接口
		String responseBody = requestTtService(RequestMethod.GET, ACTION_CATEGORY_URI, accessToken, requestBody);

		// 处理应答结果
		JSONObject result = JSON.parseObject(responseBody);
		if (result.getIntValue("code") != 0) {
			throw new IllegalStateException(responseBody);
		}
		return result.getObject("data", new TypeReference<List<AdActionInterestDTO>>() {
		});
	}

	/**
	 * 行为关键词模糊查询
	 *
	 * @param planTemp
	 * @return
	 */
	@Override
	public List<AdActionInterestDTO> selectActionKeywordList(AdPlanTempDto planTemp) throws IOException {

		// 校验参数
		Optional<AdPlanTempDto> planTempOps = Optional.ofNullable(planTemp);
		Long advertiserId = planTempOps.map(AdPlanTempDto::getAdvertiserId).orElseThrow(NullPointerException::new);

		// 构造请求参数
		JSONObject requestBody = new JSONObject().fluentPut("advertiser_id", advertiserId)
				.fluentPut("query_words", planTempOps.map(AdPlanTempDto::getQueryWords).filter(StringUtils::isNotEmpty).orElseThrow(NullPointerException::new))
				.fluentPut("action_scene", planTempOps.map(AdPlanTempDto::getActionScenes).filter(CollectionUtil::isNotEmpty).orElse(DEFAULT_ACTION_SCENES))
				.fluentPut("action_days", planTempOps.map(AdPlanTempDto::getActionDays1).orElseThrow(NullPointerException::new));

		// 获取token
		String accessToken = Objects.requireNonNull(ttAccesstokenService.fetchAccesstoken(String.valueOf(advertiserId)), "没有找到有效的AccessToken");

		// 请求接口
		String responseBody = requestTtService(RequestMethod.GET, ACTION_KEYWORD_URI, accessToken, requestBody);
		// 处理应答结果
		JSONObject result = JSON.parseObject(responseBody);
		if (result.getIntValue("code") != 0) {
			throw new IllegalStateException(responseBody);
		}
		return result.getJSONObject("data").getObject("list", new TypeReference<List<AdActionInterestDTO>>() {
		});
	}

	/**
	 * 兴趣类目列表查询
	 *
	 * @param planTemp
	 * @return
	 */
	@Override
	public List<AdActionInterestDTO> selectInterestCategoryList(AdPlanTempDto planTemp) throws IOException {

		// 校验参数
		Optional<AdPlanTempDto> planTempOps = Optional.ofNullable(planTemp);
		Long advertiserId = planTempOps.map(AdPlanTempDto::getAdvertiserId).orElseThrow(NullPointerException::new);

		JSONObject requestBody = new JSONObject().fluentPut("advertiser_id", advertiserId);

		// 获取token
		String accessToken = Objects.requireNonNull(ttAccesstokenService.fetchAccesstoken(String.valueOf(advertiserId)), "没有找到有效的AccessToken");

		// 请求接口
		String responseBody = requestTtService(RequestMethod.GET, INTEREST_CATEGORY_URI, accessToken, requestBody);
		// 处理应答结果
		JSONObject result = JSON.parseObject(responseBody);
		if (result.getIntValue("code") != 0) {
			throw new IllegalStateException(responseBody);
		}
		return result.getObject("data", new TypeReference<List<AdActionInterestDTO>>() {
		});
	}

	/**
	 * 兴趣关键词模糊查询
	 *
	 * @param planTemp
	 * @return
	 */
	@Override
	public List<AdActionInterestDTO> selectInterestKeywordList(AdPlanTempDto planTemp) throws IOException {

		// 校验参数
		Optional<AdPlanTempDto> planTempOps = Optional.ofNullable(planTemp);
		Long advertiserId = planTempOps.map(AdPlanTempDto::getAdvertiserId).orElseThrow(NullPointerException::new);

		// 构造请求参数
		JSONObject requestBody = new JSONObject().fluentPut("advertiser_id", advertiserId).fluentPut("query_words", planTempOps.map(AdPlanTempDto::getQueryWords).orElseThrow(NullPointerException::new));

		// 获取token
		String accessToken = Objects.requireNonNull(ttAccesstokenService.fetchAccesstoken(String.valueOf(advertiserId)), "没有找到有效的AccessToken");
		// 请求接口
		String responseBody = requestTtService(RequestMethod.GET, INTEREST_KEYWORD_URI, accessToken, requestBody);
		// 处理应答结果
		JSONObject result = JSON.parseObject(responseBody);
		if (result.getIntValue("code") != 0) {
			throw new IllegalStateException(responseBody);
		}

		return result.getJSONObject("data").getObject("list", new TypeReference<List<AdActionInterestDTO>>() {
		});
	}

	/**
	 * 行为兴趣ID查询关键词列表
	 *
	 * @param planTemp
	 * @return
	 */
	@Override
	public List<AdActionInterestDTO> selectActionInterestKeywordList(AdPlanTempDto planTemp) throws IOException {
		// 校验参数
		Optional<AdPlanTempDto> planTempOps = Optional.ofNullable(planTemp);
		Long advertiserId = planTempOps.map(AdPlanTempDto::getAdvertiserId).orElseThrow(NullPointerException::new);
		String targetType = planTempOps.map(AdPlanTempDto::getTargetType).filter(StringUtils::isNotEmpty).orElseThrow(NullPointerException::new);

		// 构造请求参数
		JSONObject requestBody = new JSONObject().fluentPut("advertiser_id", advertiserId)
				.fluentPut("id", planTempOps.map(AdPlanTempDto::getActionInterestId).orElseThrow(NullPointerException::new))
				.fluentPut("tag_type", planTempOps.map(AdPlanTempDto::getSearchType).filter(StringUtils::isNotEmpty).orElseThrow(NullPointerException::new))
				.fluentPut("targeting_type", targetType);
		if ("ACTION".equals(targetType)) {
			requestBody.fluentPut("action_scene", planTempOps.map(AdPlanTempDto::getActionScenes).filter(CollectionUtil::isNotEmpty).orElse(DEFAULT_ACTION_SCENES))
					.fluentPut("action_days", planTempOps.map(AdPlanTempDto::getActionDays1).orElseThrow(() -> new IllegalArgumentException("行为天数不能为空")));
		}

		// 获取token
		String accessToken = Objects.requireNonNull(ttAccesstokenService.fetchAccesstoken(String.valueOf(advertiserId)), "没有找到有效的AccessToken");

		// 请求接口
		String responseBody = requestTtService(RequestMethod.GET, ACTION_INTEREST_KEYWORD_URI, accessToken, requestBody);
		// 处理应答结果
		JSONObject result = JSON.parseObject(responseBody);
		if (result.getIntValue("code") != 0) {
			throw new IllegalStateException(responseBody);
		}

		return result.getJSONObject("data").getObject("keywords", new TypeReference<List<AdActionInterestDTO>>() {
		});
	}

	private String requestTtService(RequestMethod method, String uri, String accessToken, JSONObject body) throws IOException {
		try (CloseableHttpClient client = HttpClients.createDefault()) {
			HttpEntityEnclosingRequestBase httpEntityRequest = new HttpEntityEnclosingRequestBase() {
				@Override
				public String getMethod() {
					return method.name();
				}
			};
			httpEntityRequest.setURI(URI.create(uri));
			httpEntityRequest.addHeader("Access-Token", accessToken);
			httpEntityRequest.setEntity(new StringEntity(body.toJSONString(), ContentType.APPLICATION_JSON));
			try (CloseableHttpResponse response = client.execute(httpEntityRequest)) {
				return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
			}
		}
	}


	/**
	 * 查询广告计划临时信息
	 *
	 * @param id 广告计划临时ID
	 * @return 广告计划临时信息
	 */
	@Override
	public AdPlanTemp selectAdPlanTempById(Long id) {
		return baseMapper.selectById(id);
	}


	/**
	 * 插入广告计划数据
	 *
	 * @param adPlanTempDto
	 * @return
	 */
	@Override
	public R saveAdPlanTempOperate(AdPlanTempDto adPlanTempDto) {
		R check = this.baseCheck(adPlanTempDto);
		if (check != null) {
			return check;
		}
		int i;
		if (Objects.isNull(adPlanTempDto.getId())) {
			i = baseMapper.insert(adPlanTempDto);
		} else {
			i = baseMapper.updateById(adPlanTempDto);
		}
		if (SqlHelper.retBool(i)) {
			return R.ok(adPlanTempDto.getId().toString(), "操作成功");
		} else {
			return R.failed("操作失败");
		}
	}

	private R baseCheck(AdPlanTempDto adPlanTempDto){
		if (null == adPlanTempDto) {
			return R.failed("param is empty");
		}
		if (null == adPlanTempDto.getAdvertiserId()) {
			return R.failed("advertiserId is empty");
		}

		if (null == adPlanTempDto.getCampaignId()) {
			return R.failed("campaignId is empty");
		}
		Integer userId = SecurityUtils.getUser().getId();
		adPlanTempDto.setUserId(userId.longValue());
		if (StringUtils.isBlank(adPlanTempDto.getDeliveryRange())) {
			return R.failed("投放范围不能为空");
		}
		if (StringUtils.equals(adPlanTempDto.getDeliveryRange(), "DEFAULT")) {
			adPlanTempDto.setUnionVideoType(null);
			adPlanTempDto.setSuperiorPopularityType(null);
		}
		if (StringUtils.equals(adPlanTempDto.getDeliveryRange(), "UNION") && StringUtils.isBlank(adPlanTempDto.getUnionVideoType())) {
			return R.failed("投放形式不能为空");
		}
		if (adPlanTempDto.getAppId() == null) {
			return R.failed("应用不能为空");
		}
		if (adPlanTempDto.getGameId() == null) {
			return R.failed("子游戏不能为空");
		}
		// 资产ID，逗号分割
		if (StringUtils.isBlank(adPlanTempDto.getAssetIds())) {
			return R.failed("资产不能为空");
		}

		// 转化来源类型  应用下载SDK AD_CONVERT_SOURCE_TYPE_SDK
		String convertSourceType = adPlanTempDto.getConvertSourceType();
		// 转化目标
		String convertType = adPlanTempDto.getConvertType();
		// 深度转化目标
		String deepExternalAction = adPlanTempDto.getDeepExternalAction();
		// 监测链接组ID集合
		String trackUrlGroupIds = adPlanTempDto.getTrackUrlGroupId();

		if (StringUtils.isBlank(convertSourceType)) {
			return R.failed("转化跟踪方式不能为空");
		}

		if (StringUtils.isBlank(convertType)) {
			return R.failed("转化目标不能为空");
		}

		if (StringUtils.isBlank(trackUrlGroupIds)) {
			return R.failed("转化不能为空");
		}

		//新建定向
		if (null == adPlanTempDto.getAudienceId()) {
			//修复第一次选择已有定向，点击上一步选择新建定向时定向ID没有清空的BUG
			//@TableField(updateStrategy = FieldStrategy.IGNORED)
			//当定向包主键为空 ，判断新建定向包的参数
			if (StringUtils.equals(adPlanTempDto.getDownloadType(), "EXTERNAL_URL")) {
				//落地页
				if (StringUtils.isBlank(adPlanTempDto.getExternalUrl())) {
					return R.failed("广告计划落地页链接externalUrl不能为空");
				}
			}

			if (StringUtils.equals(adPlanTempDto.getDistrict(), "CITY") || StringUtils.equals(adPlanTempDto.getDistrict(), "COUNTY")) {
				if (StringUtils.isBlank(adPlanTempDto.getCity())) {
					return R.failed("省市或区县不能为空");
				}
			}

			if (StringUtils.equals(adPlanTempDto.getDistrict(), "BUSINESS_DISTRICT") && StringUtils.isBlank(adPlanTempDto.getBusinessIds())) {
				return R.failed("商圈不能为空");

			}
			if (StringUtils.isBlank(adPlanTempDto.getDistrict())) {
				adPlanTempDto.setCity(null);
				adPlanTempDto.setLocationType(null);
				adPlanTempDto.setBusinessIds(null);
			}
			if (null == adPlanTempDto.getRetargetingTags() || 1 == adPlanTempDto.getRetargetingTags()) {
				adPlanTempDto.setRetargetingTagsExclude(null);
				adPlanTempDto.setRetargetingTagsInclude(null);
			} else if (2 == adPlanTempDto.getRetargetingTags()) {
				if (StringUtils.isEmpty(adPlanTempDto.getRetargetingTagsExclude()) && StringUtils.isEmpty(adPlanTempDto.getRetargetingTagsInclude())) {
					return R.failed("人群自定义包定向和排除不能同时为空");
				}
			}
			if (null != adPlanTempDto.getDeviceBrandType() && 2 == adPlanTempDto.getDeviceBrandType() && StringUtils.isBlank(adPlanTempDto.getDeviceBrand())) {
				//按品牌
				return R.failed("品牌不能为空");
			}
			if (null != adPlanTempDto.getDeviceBrandType() && 1 == adPlanTempDto.getDeviceBrandType()) {
				//不限品牌时清空前端传的值
				adPlanTempDto.setDeviceBrand(null);
			}
			if (null != adPlanTempDto.getLaunchPriceType() && 2 == adPlanTempDto.getLaunchPriceType() && (null == adPlanTempDto.getLaunchPriceFrom() || null == adPlanTempDto.getLaunchPriceTo())) {
				return R.failed("手机价格区间不允许为空");
			}
			if (null != adPlanTempDto.getLaunchPriceType() && 2 == adPlanTempDto.getLaunchPriceType() && (adPlanTempDto.getLaunchPriceFrom() >= adPlanTempDto.getLaunchPriceTo())) {
				return R.failed("手机价格区间最小值须小于最大值");
			}
			if (null != adPlanTempDto.getDeviceBrandType() && 1 == adPlanTempDto.getLaunchPriceType()) {
				//不限手机价格时清空前端传的值
				adPlanTempDto.setLaunchPriceFrom(null);
				adPlanTempDto.setLaunchPriceTo(null);
			}
			adPlanTempDto.setHideIfConverted(Optional.ofNullable(adPlanTempDto.getHideIfConverted()).orElse("NO_EXCLUDE"));
			//add chengang 20210712 自定义定向逻辑是新增行为兴趣的校验
			if ("CUSTOM".equals(adPlanTempDto.getInterestActionMode())) {
				if (StringUtils.isBlank(adPlanTempDto.getActionScene())) {
					return R.failed("自定义行为兴趣场景情况下,行为场景不能为空");
				}
				if (StringUtils.isBlank(adPlanTempDto.getActionDays())) {
					return R.failed("自定义行为兴趣场景情况下,用户行为天数不能为空");
				}
				if (StringUtils.isBlank(adPlanTempDto.getActionCategories())
						&& StringUtils.isBlank(adPlanTempDto.getActionWords())
						&& StringUtils.isBlank(adPlanTempDto.getInterestCategories())
						&& StringUtils.isBlank(adPlanTempDto.getInterestWords())) {
					return R.failed("行为类目词、行为关键词、兴趣类目词、兴趣关键词不能全部为空");
				}
			}
		} else {
			// 如果同时传定向包ID和自定义用户定向参数时，仅定向包中的定向生效  so定向包里面的行为兴趣可以先不用管
			// 设置临时表定向人群和排除人群
			AudiencePackage audiencePackage = audiencePackageService.getOne(Wrappers.<AudiencePackage>query().lambda().eq(AudiencePackage::getIdAdPlatform, adPlanTempDto.getAudienceId()));
			if (audiencePackage == null) {
				throw new BusinessException(11, "定向包id=" + adPlanTempDto.getAudienceId() + "不存在");
			}
			adPlanTempDto.setRetargetingTagsInclude(audiencePackage.getRetargetingTags());
			adPlanTempDto.setRetargetingTagsExclude(audiencePackage.getRetargetingTagsExclude());
		}


		String smartBidType = adPlanTempDto.getSmartBidType();
		if (StringUtils.isBlank(smartBidType)) {
			return R.failed("投放场景不允许为空");
		}

		// 放量投放
		if (StringUtils.equals(smartBidType, "SMART_BID_CONSERVATIVE")) {
			adPlanTempDto.setFlowControlMode("FLOW_CONTROL_MODE_FAST");
			adPlanTempDto.setScheduleType("SCHEDULE_FROM_NOW");
			adPlanTempDto.setStartTime(null);
			adPlanTempDto.setEndTime(null);
		}
		//常规投放
		if (StringUtils.equals(smartBidType, "SMART_BID_CUSTOM")) {
			if (StringUtils.isBlank(adPlanTempDto.getFlowControlMode())) {
				return R.failed("竞价策略不允许为空");
			}
			if (StringUtils.isBlank(adPlanTempDto.getScheduleType())) {
				return R.failed("投放时间不允许为空");
			}
			if (StringUtils.equals(adPlanTempDto.getScheduleType(), "SCHEDULE_FROM_NOW")) {
				adPlanTempDto.setStartTime(null);
				adPlanTempDto.setEndTime(null);
			}

			//常规投放-选择了深度优化方式且竞价策略= FLOW_CONTROL_MODE_SMOOTH 头条会返回 ：常规投放下控制成本上限不支持深度转化目标
			if (StringUtils.isNotBlank(adPlanTempDto.getDeepExternalAction())) {
				if ("FLOW_CONTROL_MODE_SMOOTH".equals(adPlanTempDto.getFlowControlMode())) {
					return R.failed("常规投放下控制成本上限不支持深度转化目标");
				}
			}

			//转化目标为付费的情况下竞价策略不能是优先低成本(FLOW_CONTROL_MODE_SMOOTH)
			if (TtConvertTypeEnum.AD_CONVERT_TYPE_PAY.getType().equals(adPlanTempDto.getConvertType())) {
				if ("FLOW_CONTROL_MODE_SMOOTH".equals(adPlanTempDto.getFlowControlMode())) {
					return R.failed("常规投放-付费的情况下竞价策略不能是优先低成本");
				}
			}
		}

		if (StringUtils.equals(adPlanTempDto.getScheduleType(), "SCHEDULE_START_END")) {
			if (StringUtils.isBlank(adPlanTempDto.getStartTime()) || StringUtils.isBlank(adPlanTempDto.getEndTime())) {
				return R.failed("广告计划设置投放时间段，开始时间和结束时间不允许为空");
			}

			adPlanTempDto.setStartTime(DateUtil.getDateFormat("yyyy-MM-dd HH:mm").format(DateUtil.stringToDate(adPlanTempDto.getStartTime(), "yyyy-M-dd HH:mm")));
			adPlanTempDto.setEndTime(DateUtils.getDateFormat("yyyy-MM-dd HH:mm").format(DateUtil.stringToDate(adPlanTempDto.getEndTime(), "yyyy-MM-dd HH:mm")));
		}

		if (StringUtils.isNotBlank(adPlanTempDto.getPricing()) && (adPlanTempDto.getPricing().equals("PRICING_OCPM") || adPlanTempDto.getPricing().equals("PRICING_OCPC"))) {
			if (StringUtils.equals(adPlanTempDto.getDeliveryRange(), "DEFAULT") && adPlanTempDto.getPricing().equals("PRICING_OCPC")) {
				//当投放范围为默认的时候，如果值为穿山甲，将付费方式设置为
				adPlanTempDto.setPricing("PRICING_OCPM");
			}
			if (null == adPlanTempDto.getBudget()) {
				return R.failed("日预算不允许为空");
			}
			if (adPlanTempDto.getBudget().compareTo(new BigDecimal(300)) == -1 || adPlanTempDto.getBudget().compareTo(new BigDecimal(9999999.99)) == 1) {
				return R.failed("当出价为OCPM或OCPC,预算不能小于300元,并不超过9999999.99元");
			}
			/*pricing为"OCPC"时取值范围：0.1-10000元；pricing为"OCPM"时取值范围：0.1-10000元；出价不能大于预算否则会报错*/
			if (null != adPlanTempDto.getCpaBid()) {
				Boolean flag = adPlanTempDto.getCpaBid().compareTo(new BigDecimal("0.1")) == -1 || adPlanTempDto.getCpaBid().compareTo(new BigDecimal(10000)) == 1 || adPlanTempDto.getCpaBid().compareTo(adPlanTempDto.getBudget()) == 1;
				if (flag) {
					return R.failed("pricing为OCPC或OCPC时取值范围：0.1-10000元.并且不能大于预算");
				}
			} else {
				return R.failed("目标出价不能为空");
			}
		}

		//付费-无的场景，存在每次付费的深度优化方式
		if (StringUtils.isBlank(adPlanTempDto.getDeepExternalAction()) && !"AD_CONVERT_TYPE_PAY".equals(convertType)) {
			adPlanTempDto.setDeepBidType(null);
		}

		//深度优化方式
		String deepBidType = adPlanTempDto.getDeepBidType();

		//深度优化出价 手动出价下才有deepCpabid
		BigDecimal deepCpabid = adPlanTempDto.getDeepCpabid();

		//深度转化ROI系数, 范围(0,5]，精度：保留小数点后四位, deep_bid_type为"ROI_COEFFICIENT"时必填
		BigDecimal roiGoal = adPlanTempDto.getRoiGoal();

		//当投放范围为穿山甲时，选择了深度转化目标时，深度优化方式可以为空，postman验证是通过的
//		if (StringUtils.isNotBlank(deepExternalAction) && StringUtils.isBlank(deepBidType)) {
//			return R.failed("转化目标中含有深度转化时,深度优化方式必填");
//		}

		if (StringUtils.equals(deepBidType, "ROI_COEFFICIENT")) {
			if (roiGoal == null) {
				return R.failed("深度转化ROI系数不能为空");
			} else if (roiGoal.compareTo(new BigDecimal("0")) < 0 || roiGoal.compareTo(new BigDecimal("5")) > 0) {
				return R.failed("深度转化ROI系数范围(0,5]，精度：保留小数点后四位");
			}
		} else if (StringUtils.equals(deepBidType, "DEEP_BID_MIN")) {
			if (deepCpabid == null) {
				return R.failed("深度优化出价不能为空");
			} else if (deepCpabid.compareTo(new BigDecimal("0.1")) < 0 || deepCpabid.compareTo(new BigDecimal("10000")) > 0) {
				return R.failed("深度优化出价取值范围：0.1~10000元");
			}
		}

		if (StringUtils.isBlank(deepBidType)) {
			adPlanTempDto.setDeepCpabid(null);
			adPlanTempDto.setRoiGoal(null);
		}
		return null;
	}

	/**
	 * 获取用户某个广告账号，广告组添加的广告计划数据（模板）
	 *
	 * @param adPlanTempDto
	 */
	@Override
	public R getUserPlanTemp(AdPlanTempDto adPlanTempDto) {
		if (null == adPlanTempDto) {
			return R.failed("参数为空");
		}
		if (null == adPlanTempDto.getAdvertiserId()) {
			return R.failed("未输入广告账户id");
		}
		AdPlanTempVo adPlanTempVo = null;
		if (Objects.nonNull(adPlanTempDto.getId())) {
			adPlanTempVo = baseMapper.getUserPlanTempById(adPlanTempDto);
			if (Objects.isNull(adPlanTempVo)) {
				return R.failed("广告计划临时表中无此广告计划");
			}
		} else {
			//获取当前用户最后一次创建的广告计划
			Integer userId = SecurityUtils.getUser().getId();
			adPlanTempDto.setUserId(userId.longValue());
			adPlanTempVo = baseMapper.getUserPlanTempOne(adPlanTempDto);
		}
		if (Objects.isNull(adPlanTempVo)) {
			return R.ok(null);
		}
		Long audienceId = adPlanTempVo.getAudienceId();
		if (Objects.nonNull(audienceId)) {
			AudiencePackage ap = audiencePackageMapper.selectOne(Wrappers.<AudiencePackage>query().lambda()
					.eq(AudiencePackage::getIdAdPlatform, audienceId).last("LIMIT 1"));
			if (Objects.isNull(ap)) {
				return R.failed("定向包组表中无此定向包");
			}
			adPlanTempVo.setPackageName(ap.getName());
			adPlanTempVo.setDescription(ap.getDescription());
			adPlanTempVo.setLandingTypeName(ap.getLandingTypeName());
			adPlanTempVo.setDeliveryRangeName(ap.getDeliveryRangeName());
		}
		return R.ok(adPlanTempVo);
	}


}
